/*
 * Copyright (C) Francisco Morero Peyrona. All rights reserved.
 *
 * This software is published under the terms of Open Source 
 * License version 1.1, a copy of which has been included with this
 * distribution in the License.txt file.  
 */

package jdbcmanager.swing;

import java.util.*;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/**
 * A JList that uses JCheckBox components as items
 *
 * @author Francisco Morero Peyrona
 */
public final class JCheckList extends JList
{
   public JCheckList()
   {
      super();

      init();
   }

   public JCheckList( ListModel dataModel )
   {
      super( dataModel );

      init();
   }

   public JCheckList( Object[] listData )
   {
      super();

      init();

      for( int n = 0; n < listData.length; n++ )
         add( listData[n].toString() );
   }

   public JCheckList( Vector listData )
   {
      this( listData.toArray() );
   }

   //-------------------------------------------------------------------------//

   public void add( String sCaption )
   {
      DefaultListModel model = (DefaultListModel) getModel();
      JCheckBox        check = new JCheckBox( sCaption );
                       check.setFont( getFont() );
                       check.setOpaque( true );

      model.addElement( check );
   }

   public void add( String sCaption, boolean bSelected )
   {
      DefaultListModel model = (DefaultListModel) getModel();
      JCheckBox        check = new JCheckBox( sCaption );
                       check.setFont( getFont() );
                       check.setOpaque( true );
                       check.setSelected( bSelected );

      model.addElement( check );
   }

   public void add( int nIndex, String sCaption )
   {
      DefaultListModel model = (DefaultListModel) getModel();

      model.add( nIndex, new JCheckBox( sCaption ) );
   }

   public void add( int nIndex, String sCaption, boolean bSelected )
   {
      DefaultListModel model = (DefaultListModel) getModel();
      JCheckBox        check = new JCheckBox( sCaption );
                       check.setFont( getFont() );
                       check.setOpaque( true );
                       check.setSelected( bSelected );

      model.add( nIndex, check );
   }

   public JCheckBox[] getSelectedChecks()
   {
      ListModel model = getModel();
      int      nItems = model.getSize();
      Vector   vSel   = new Vector();

      for( int n = 0; n < nItems; n++ )
      {
         JCheckBox check = (JCheckBox) model.getElementAt( n );

         if( check.isSelected() )
            vSel.add( check );
      }

      // From Vector to Array
      JCheckBox[] chk = new JCheckBox[ vSel.size() ];
      vSel.copyInto( chk );

      return chk;
   }

   public void selectAll()
   {
      ListModel model = getModel();
      int      nItems = model.getSize();

      for( int n = 0; n < nItems; n++ )
         ((JCheckBox) model.getElementAt( n )).setSelected( true );

      this.repaint();
   }

   public void deselectAll()
   {
      ListModel model = getModel();
      int      nItems = model.getSize();

      for( int n = 0; n < nItems; n++ )
         ((JCheckBox) model.getElementAt( n )).setSelected( false );

      this.repaint();
   }

   public void invertSelection()
   {
      ListModel model = getModel();
      int      nItems = model.getSize();

      for( int n = 0; n < nItems; n++ )
      {
         JCheckBox check = (JCheckBox) model.getElementAt( n );
                   check.setSelected( ! check.isSelected() );
      }

      this.repaint();
   }

   //-------------------------------------------------------------------------//

   private void init()
   {
      setModel( new DefaultListModel() );
      setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
      setCellRenderer( new ThisCellRenderer() );

      addMouseListener( new MouseAdapter()
      {
         public void mouseReleased( MouseEvent evt )
         {
            if( evt.getClickCount() == 2 )
               changeSelectedItemStatus();
         }
      });

      addKeyListener( new KeyAdapter()
      {
         public void keyTyped( KeyEvent evt )
         {
            if( evt.getKeyChar() == KeyEvent.VK_SPACE )
               changeSelectedItemStatus();
         }
      });
   }


   private void changeSelectedItemStatus()
   {
      JCheckBox check = (JCheckBox) getSelectedValue();

      // If nothing is currently selected, there is nothing to do
      if( check != null && check.isEnabled() )
      {
         check.setSelected( ! check.isSelected() );

         SwingUtilities.invokeLater( new Runnable()
         {
            public void run()
            {
               invalidate();
               repaint();
            }
         } );
      }
   }

   //-------------------------------------------------------------------------//
   // INNER CLASS: Cell Renderer
   //-------------------------------------------------------------------------//
   final class ThisCellRenderer implements ListCellRenderer
   {
      // This is the only method defined by ListCellRenderer.
      public Component getListCellRendererComponent( JList list,
                                                     Object value,        // value to display
                                                     int index,           // cell index
                                                     boolean bSelected,   // is the cell selected
                                                     boolean bHasFocus )  // the list and the cell have the focus
      {
         JCheckBox check = (JCheckBox) value;

         if( bSelected )
         {
            check.setBackground( list.getSelectionBackground() );
            check.setForeground( list.getSelectionForeground() );
         }
         else
         {
            check.setBackground( list.getBackground() );
            check.setForeground( list.getForeground() );
         }

         check.setEnabled( list.isEnabled() );

         return check;
      }
   }
}